package com.alex.web.db.dao;

import com.alex.web.bean.BaseEntity;
import com.alex.web.db.JedisKey;
import com.alex.web.db.domain.PageControl;
import com.alex.web.db.domain.PageInfo;
//import com.misi.log.MISILogger;
//import com.misi.log.MISILoggerFactory;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.support.SqlSessionDaoSupport;

import javax.annotation.Resource;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * delete(T pk), (M entity), getEntityById(T pk)添加了缓存操作；
 * 其他需要操作缓存的方法，在具体实现中重写
 *
 * @param <T>
 * @param <M>
 */
public abstract class BaseDao<T extends Serializable, M extends BaseEntity> extends SqlSessionDaoSupport implements IDao<T, M>, JedisDao {

//    private final MISILogger logger = MISILoggerFactory.getLogger(this.getClass());

    public static final String insertSelective = ".insertSelective";
    public static final String updateByPrimaryKeySelective = ".updateByPrimaryKeySelective";
    public static final String selectByPrimaryKey = ".selectByPrimaryKey";
    public static final String selectByPrimaryKeys = ".selectByPrimaryKeys";
    public static final String getListByEntityAndPageInfo = ".getListByEntityAndPageInfo";
    public static final String getTotalByEntity = ".getTotalByEntity";
    public static final String deleteByPrimaryKey = ".deleteByPrimaryKey";
//    public static final String deleteByEntity = ".deleteByEntity";

    private Class<M> curClassType = null;

    @Resource
    public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
        super.setSqlSessionFactory(sqlSessionFactory);
    }

    public String getMapperNameSpace() {
        return getClass().getName();
    }

    public JedisKey getUsedJedisKey() {
        return JedisKey.defaultNotUse;
    }

    public BaseDao() {
        if (getClass().getGenericSuperclass() instanceof ParameterizedType) {
            curClassType = (Class<M>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[1];
        }
    }

    /**
     * 从缓存删除
     *
     * @param pk 主键
     * @return
     */
    public Boolean deleteCacheByPk(T pk) {
        boolean flag = false;
//        if (JedisKey.defaultNotUse != this.getUsedJedisKey()) {
//            try {
//                flag = ShardJedisTool.getInstance().del(getUsedJedisKey(), pk);
//            } catch (Exception e) {
//                Map<String, Object> map = new HashMap<String, Object>();
//                map.put("pk", pk);
//                logger.error(e, map, "");
//            }
//        }
        return flag;
    }

    /**
     * SQL参数包装
     *
     * @param entity
     * @param pageInfo
     * @param whereSql
     * @param orderBySql
     * @return
     */
    private Map<String, Object> getMapParams(M entity, PageInfo pageInfo, String whereSql, String orderBySql) {
        Map<String, Object> map = new HashMap<String, Object>();
        if (null != entity) {
            map.put("entity", entity);
        }
        if (null != pageInfo) {
            map.put("pageInfo", pageInfo);
        }
        if (null != whereSql) {
            map.put("whereSql", whereSql);
        }
        if (null != orderBySql) {
            map.put("orderBy", orderBySql);
        }
        return map;
    }

    public int insert(M entity) {
        return this.getSqlSession().insert(this.getMapperNameSpace() + insertSelective, entity);
    }

    public int update(M entity) {

        Object ret = this.getSqlSession().update(this.getMapperNameSpace() + updateByPrimaryKeySelective, entity);

//        if (JedisKey.defaultNotUse != this.getUsedJedisKey()) {
//            try {
//                Boolean flag = ShardJedisTool.getInstance().del(this.getUsedJedisKey(), entity.getId());
//                if (logger.isDebugEnabled()) {
//                    logger.debug("delete jedis " + curClassType.getSimpleName() + " when update entity " + " key:" + entity.getId() + ", delResult:" + flag);
//                }
//            } catch (Exception e) {
//                logger.error(e, entity, "");
//            }
//        }

        return ((Integer) ret).intValue();
    }

    /**
     * 如果有缓存，则先删除缓存
     *
     * @param pk
     * @return
     */
    public int delete(T pk) {
        Object e = this.getSqlSession().delete(this.getMapperNameSpace() + deleteByPrimaryKey, pk);
        this.deleteCacheByPk(pk);
        return ((Integer) e).intValue();
    }

//    public int deleteByEntity(M entity) {
//        Object e = this.getSqlSession().delete(this.getMapperNameSpace() + ".deleteByEntity", entity);
//        return ((Integer) e).intValue();
//    }

    public M getEntityById(T pk) {

        M returnObj = null;
        //jedis 服务使用状态
//        boolean jedisUseStatus = true;
//        String entityJsonStr = null;
//        if (JedisKey.defaultNotUse != this.getUsedJedisKey()) {
//            try {
//                entityJsonStr = ShardJedisTool.getInstance().get(this.getUsedJedisKey(), pk);
//            } catch (Exception e) {
//                Map<String, Object> map = new HashMap<String, Object>();
//                map.put("pk", pk);
//                logger.error(e, map, "");
//
//                jedisUseStatus = false;
//            }
//
//            try {
//                if (StringUtils.isNotBlank(entityJsonStr)) {
//                    if (logger.isDebugEnabled()) {
//                        logger.debug("load jedis " + curClassType.getSimpleName() + " key:" + pk + " value: " + entityJsonStr);
//                    }
//                    returnObj = GsonUtil.fromJson(entityJsonStr, curClassType);
//                }
//            } catch (JsonSyntaxException e) {
//                Map<String, Object> map = new HashMap<String, Object>();
//                map.put("pk", pk);
//                map.put("entityJsonStr", entityJsonStr);
//                logger.error(e, map, "");
//            }
//        }

//        if (returnObj != null) {
//            return returnObj;
//        }

        returnObj = this.getSqlSession().selectOne(this.getMapperNameSpace() + selectByPrimaryKey, pk);
//        if (JedisKey.defaultNotUse != this.getUsedJedisKey() && returnObj != null && jedisUseStatus) {
//            String objJson =GsonUtil.toJson(returnObj, curClassType);
//            try {
//                ShardJedisTool.getInstance().set(this.getUsedJedisKey(), pk, objJson);
//                if (logger.isDebugEnabled()) {
//                    logger.debug("insert jedis " + curClassType.getSimpleName() + " when getEntityById, key:" + pk + " value: " + objJson);
//                }
//            } catch (Exception e) {
//                Map<String, Object> map = new HashMap<String, Object>();
//                map.put("pk", pk);
//                map.put("returnObj", returnObj);
//                logger.error(e, map, "");
//            }
//        }
        return returnObj;
    }

    public M getEntityByObj(M entity) {
        return (M) this.getSqlSession().selectOne(this.getMapperNameSpace() + getListByEntityAndPageInfo, this.getMapParams(entity, (PageInfo) null, null, (String) null));
    }

    public M getEntityByObj(M entity, String where) {
        return (M) this.getSqlSession().selectOne(this.getMapperNameSpace() + getListByEntityAndPageInfo, this.getMapParams(entity, (PageInfo) null, where, (String) null));
    }


    public int getCountByObj(M entity) {
        Object e = this.getSqlSession().selectOne(this.getMapperNameSpace() + getTotalByEntity, this.getMapParams(entity, (PageInfo) null, null, (String) null));
        return ((Integer) e).intValue();
    }

    /**
     * @param entity
     * @param where
     * @return
     */
    public long getCountByObj(M entity, String where) {
        Object e = this.getSqlSession().selectOne(this.getMapperNameSpace() + getTotalByEntity, this.getMapParams(entity, (PageInfo) null, where, (String) null));
        return ((Integer) e).intValue();
    }

    /**
     * @param entity
     * @param pageInfo
     * @param whereSql
     * @return
     */
    public PageControl<M> getPageByObj(M entity, PageInfo pageInfo, String whereSql) {
        return getPageByObj(entity, pageInfo, whereSql, null);
    }

    /**
     * @param entity
     * @param pageInfo
     * @param whereSql
     * @param orderBySql
     * @return
     */
    public PageControl<M> getPageByObj(M entity, PageInfo pageInfo, String whereSql, String orderBySql) {
        PageControl page = new PageControl();
        Object list = new ArrayList();

        long total = this.getCountByObj(entity, whereSql);
        if (total > 0) {
            list = this.getListByObj(entity, pageInfo, whereSql, orderBySql);
        }

        if (list != null) {
            page.setTotal(total);
            page.setEntityList((List) list);
        }

        page.setNumber(pageInfo.getPage());
        page.setSize(pageInfo.getSize());

        return page;
    }


    public List<M> getAllEntityObj() {
        return this.getListByObj((M) null, (String) null);
    }

    /**
     * @param entity
     * @return
     */
    public List<M> getListByObj(M entity) {
        return this.getListByObj(entity, (PageInfo) null, (String) null, (String) null);
    }

    /**
     * @param entity
     * @param whereSql
     * @return
     */
    public List<M> getListByObj(M entity, String whereSql) {
        return this.getListByObj(entity, (PageInfo) null, whereSql, (String) null);
    }

    /**
     * @param entity
     * @param pageInfo
     * @param whereSql
     * @return
     */
    public List<M> getListByObj(M entity, PageInfo pageInfo, String whereSql) {
        return this.getListByObj(entity, pageInfo, whereSql, (String) null);
    }

    /**
     * @param entity
     * @param pageInfo
     * @param whereSql
     * @param orderBySql
     * @return
     */
    public List<M> getListByObj(M entity, PageInfo pageInfo, String whereSql, String orderBySql) {
        return this.getSqlSession().selectList(this.getMapperNameSpace() + getListByEntityAndPageInfo, this.getMapParams(entity, pageInfo, whereSql, orderBySql));
    }

}
